package com.biz.primus.ms.promotion.dao.po;

import com.biz.primus.base.enums.PromotionTypeEnum;
import com.biz.primus.base.exception.utils.AssertUtils;
import com.biz.primus.common.utils.JsonUtils;
import com.biz.primus.model.promotion.enums.PromotionGiftTypeEnum;
import com.biz.primus.model.promotion.enums.PromotionTargetLimitTypeEnum;
import com.biz.primus.model.promotion.exception.PromotionExceptionType;
import com.biz.primus.model.promotion.vo.OrderPromotionDetailVo;
import com.biz.primus.model.promotion.vo.PurchaseGiftRuleVo;
import com.biz.primus.model.promotion.vo.PurchaseGiftVo;
import com.biz.primus.model.promotion.vo.req.OrderPromotionReqDetailVo;
import java.util.List;
import java.util.Objects;
import javax.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 买赠/满赠促销
 *
 * @author david-liu
 */
@Entity
@Getter
@Setter
public class PurchaseGiftPromotion extends BasePromotion {
    private static final long serialVersionUID = -3766694021627689370L;

    // 促销门槛限制方式(按照金额还是按照数量)
    @Column(nullable = false)
    @Enumerated(value = EnumType.STRING)
    private PromotionTargetLimitTypeEnum limitType;

    /**
     * 限制金额(单位: 分)
     */
    private Integer limitAmount;

    /**
     * 限制数量
     */
    private Integer limitQuantity;

    // 赠品类型
    @Enumerated(value = EnumType.STRING)
    private PromotionGiftTypeEnum giftType;

    /**
     * 赠品规则详情, 存放PurchaseGiftRuleVo JSON信息
     *
     * @see PurchaseGiftRuleVo
     */
    @Column(columnDefinition = "TEXT")
    private String giftDetail;

    /**
     * 买赠活动次数上限
     */
    private Integer times;

    @Transient
    private PurchaseGiftRuleVo purchaseGiftRule;

    @Override
    public boolean isMatchPromotionRule(OrderPromotionReqDetailVo detailVo) {
        AssertUtils.isTrue(Objects.nonNull(detailVo), PromotionExceptionType.ILLEGAL_PARAMETER);
        detailVo.postProcess();
        List<Long> promotionEffectProductIds = this.getPromotionEffectProductIds(detailVo);
        if (CollectionUtils.isEmpty(promotionEffectProductIds)) {
            return false;
        }
        AssertUtils.isTrue(Objects.nonNull(this.limitType) && (Objects.nonNull(this.limitAmount) || Objects.nonNull(this.limitQuantity)), PromotionExceptionType.ILLEGAL_STATE);
        if (this.limitType == PromotionTargetLimitTypeEnum.DISCOUNT_BY_PRODUCT_AMOUNT) {
            return promotionEffectProductIds.stream().map(detailVo::getProductAmount).reduce(0, (acc, item) -> acc = acc + item) >= this.limitAmount;
        } else {
            return promotionEffectProductIds.stream().map(detailVo::getRequestProductQuantity).reduce(0, (acc, item) -> acc = acc + item) >= this.limitQuantity;
        }
    }

    @Override
    public OrderPromotionDetailVo getOrderPromotionDetail(OrderPromotionReqDetailVo reqDetailVo) {
        AssertUtils.isTrue(Objects.nonNull(reqDetailVo), PromotionExceptionType.ILLEGAL_PARAMETER);
        reqDetailVo.postProcess();
        List<Long> promotionEffectProductIds = this.getPromotionEffectProductIds(reqDetailVo);
        if (CollectionUtils.isEmpty(promotionEffectProductIds)) {
            return null;
        }
        OrderPromotionDetailVo detailVo = new OrderPromotionDetailVo();
        detailVo.setId(this.getId());
        detailVo.setName(this.getName());
        detailVo.setDescription(this.getDescription());
        detailVo.setAllowCoupon(this.getAllowCoupon());
        detailVo.setPromotionType(PromotionTypeEnum.DISCOUNT);
        detailVo.setEffectProductIds(promotionEffectProductIds);
        AssertUtils.notNull(this.limitType, PromotionExceptionType.ILLEGAL_STATE);
        PurchaseGiftRuleVo purchaseGiftRule = this.getPurchaseGiftRule();
        PurchaseGiftVo purchaseGiftVo = new PurchaseGiftVo();
        purchaseGiftVo.setGiftType(purchaseGiftRule.getGiftType());
        if (PromotionGiftTypeEnum.MEMBER_POINT == purchaseGiftRule.getGiftType()) {
            AssertUtils.isTrue(Objects.nonNull(purchaseGiftRule.getPointGiftType()) && (Objects.nonNull(purchaseGiftRule.getPointQuantity()) || Objects.nonNull(purchaseGiftRule.getPointIncreaseTimes())), PromotionExceptionType.ILLEGAL_STATE);
            purchaseGiftVo.setPointGiftType(purchaseGiftRule.getPointGiftType());
            purchaseGiftVo.setPointQuantity(purchaseGiftRule.getPointQuantity());
            purchaseGiftVo.setPointIncreaseTimes(purchaseGiftRule.getPointIncreaseTimes());
        } else if (PromotionGiftTypeEnum.PRODUCT == purchaseGiftRule.getGiftType()) {
            AssertUtils.isTrue(CollectionUtils.isNotEmpty(purchaseGiftRule.getGiftProductIds()), PromotionExceptionType.ILLEGAL_STATE);
            purchaseGiftVo.setGiftProductIds(purchaseGiftRule.getGiftProductIds());
            purchaseGiftVo.setIsGiftProductLimitStock(purchaseGiftRule.getLimitGiftProductStock());
        } else {
            AssertUtils.isTrue(MapUtils.isNotEmpty(purchaseGiftRule.getCouponIds()), PromotionExceptionType.ILLEGAL_STATE);
            purchaseGiftVo.setCoupons(purchaseGiftRule.getCouponIds());
        }
        detailVo.setPurchaseGift(purchaseGiftVo);
        return detailVo;
    }

    public PurchaseGiftRuleVo getPurchaseGiftRule() {
        if (Objects.isNull(this.purchaseGiftRule)) {
            this.purchaseGiftRule = JsonUtils.json2Obj(this.giftDetail, PurchaseGiftRuleVo.class);
        }
        AssertUtils.isTrue(Objects.nonNull(this.purchaseGiftRule) && Objects.nonNull(this.purchaseGiftRule.getGiftType()), PromotionExceptionType.ILLEGAL_STATE);
        return this.purchaseGiftRule;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
    }

}
